package com.dpp.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.dpp.config.WxHttpRequest;
import com.dpp.config.WxInformation;
import com.dpp.config.WxWayJsapi;
import com.dpp.context.BaseContext;
import com.dpp.dto.OrderDTO;
import com.dpp.entity.*;
import com.dpp.mapper.*;
import com.dpp.result.Result;
import com.dpp.service.ProductInfoService;
import com.dpp.util.HttpRequestHelper;
import com.dpp.vo.WxPayRespVO;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException;
import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;
import com.wechat.pay.contrib.apache.httpclient.notification.Notification;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.Min;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;


@Slf4j
@Service
public class WxPayService {
    @Autowired
    private CouponMapper couponMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Resource
    private WxInformation wxInformation;
    @Autowired
    private  InviteMapper inviteMapper;
    @Autowired
    private InviteRecordMapper inviteRecordMapper;
    @Resource
    private WxWayJsapi wxWayJsapi;
    @Resource
    private WxHttpRequest wxHttpRequest;
    @Autowired
    private CouponBookMapper couponBookMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ProductInfoService productInfoService;
    @Autowired
    private ActivityRecordMapper activityRecordMapper;

    public WxPayRespVO nativePay(String description, String amount, String outTradeNo) throws IOException, GeneralSecurityException, HttpCodeException, NotFoundException, URISyntaxException {
        log.info("调用统一下单API");
        String openID = BaseContext.getCurrentId();
        //设置微信请求url
        HttpPost httpPost = new HttpPost(wxInformation.getWxUrl().concat(wxWayJsapi.getOrder()));
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type", "application/json;charset=utf-8");
        // 请求body参数
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode rootNode = objectMapper.createObjectNode();
        rootNode.put("mchid", wxInformation.getMchId())
                .put("appid", wxInformation.getPublicAppid())
                .put("description", description)
                .put("notify_url", wxInformation.getNotifyUrl())
                .put("out_trade_no", outTradeNo);
        //总金额，单位为分
        Integer amount1 = Integer.valueOf(amount);

        rootNode.putObject("amount")
                .put("total", amount1);
        rootNode.putObject("payer")
                .put("openid", openID);
        log.info("请求参数 ===> " + rootNode);
        objectMapper.writeValue(bos, rootNode);
        httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
        /**
         * 完成签名并执行请求
         * */
        CloseableHttpResponse response = wxHttpRequest.sendWX(wxHttpRequest.getVerifier()).execute(httpPost);
        if (response != null) {
            String bodyAsString = EntityUtils.toString(response.getEntity());
            log.info("返回的prepay_id是 =====》 " + bodyAsString);
            JSONObject bodyobj = JSONObject.parseObject(bodyAsString);
            String prepayId = (String) bodyobj.get("prepay_id");
            WxPayRespVO vo = new WxPayRespVO();
            Long timeStamp = System.currentTimeMillis() / 1000;
            vo.setTimeStamp(timeStamp + "");
            String substring = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
            vo.setNonceStr(substring);
            String signatureStr = Stream.of(wxInformation.getPublicAppid(), String.valueOf(timeStamp), substring, "prepay_id=" + prepayId)
                    .collect(Collectors.joining("\n", "", "\n"));
            String sign = HttpRequestHelper.getSign(signatureStr, wxInformation.getPrivateKeyPath());
            vo.setPaySign(sign);
            vo.setPrepayId("prepay_id=" + prepayId);
            return vo;
        }
        return new WxPayRespVO();
    }

    public Map payNotify(HttpServletRequest request) {
        Map<String, String> result = new HashMap();
        try {
            String requestBody = HttpRequestHelper.getRequestBody(request);
            log.info("支付成功响应数据是： " + requestBody);
            JSONObject requestBodyJson = JSONObject.parseObject(requestBody);
            //微信返回的证书序列号
            String serialNo = request.getHeader("Wechatpay-Serial");
            //微信返回的随机字符串
            String nonceStr = request.getHeader("Wechatpay-Nonce");
            //微信返回的时间戳
            String timestamp = request.getHeader("Wechatpay-Timestamp");
            //微信返回的签名
            String wechatSign = request.getHeader("Wechatpay-Signature");
            // 构建request，传入必要参数
            NotificationRequest request1 = new NotificationRequest.Builder().withSerialNumber(serialNo)
                    .withNonce(nonceStr)
                    .withTimestamp(timestamp)
                    .withSignature(wechatSign)
                    .withBody(requestBody)
                    .build();
            NotificationHandler handler = new NotificationHandler(wxHttpRequest.getVerifier().getVerifier(wxInformation.getMchId()), wxInformation.getV3Key().getBytes(StandardCharsets.UTF_8));
            // 验签和解析请求体
            Notification notification = handler.parse(request1);
            // 从notification中获取解密报文
            log.info("支付成功获取解密报文： " + notification.getDecryptData());
            if (notification.getDecryptData() != null) {
                if ("TRANSACTION.SUCCESS".equals(requestBodyJson.get("event_type") + "")) {
                    JSONObject resourcePayJson = JSONObject.parseObject(notification.getDecryptData());
                    //根据微信之后返回的结果对订单进行不同的处理
                    if ("SUCCESS".equals(resourcePayJson.get("trade_state") + "")) {
                        String amount = resourcePayJson.getJSONObject("amount").get("total") + "";
                        String openid = resourcePayJson.getJSONObject("payer").get("openid") + "";
                        String outTradeNo = (String) resourcePayJson.get("out_trade_no");
                        Orders orders = orderMapper.selectByNumber(Long.valueOf(outTradeNo));
                        Integer productId = orders.getProductId();
                        ProductInfo productInfo = productInfoService.selectByID(productId);
                        if (productInfo.getId().equals(1)) {
                            if (amount.equals(productInfo.getNewUserPrice() + "")) {
                                LocalDateTime now = LocalDateTime.now();
                                ActivityRecord activityRecord1 = activityRecordMapper.selectByActivityId(openid, 1);
                                if(activityRecord1==null){
                                    ActivityRecord activityRecord = ActivityRecord.builder().openId(openid).activityId(1).recordStartTime(now).RecordFinished(ActivityRecord.start).build();
                                    activityRecordMapper.insert(activityRecord);
                                }
                            }
                        } else if (productInfo.getId().equals(2)) {
                            LocalDateTime now = LocalDateTime.now();
                            ActivityRecord activityRecord = ActivityRecord.builder().openId(openid).activityId(3).recordStartTime(now).RecordFinished(ActivityRecord.start).build();
                            activityRecordMapper.insert(activityRecord);
                        }
                        if (orders.getIsUseCoupon() == 1) {
                            couponBookMapper.updateReduceCount(openid, orders.getCouponId());
                        }
                        //发单次数加1
                        if (orders.getProductId() == 1) {
                            userMapper.updateTimes(openid);
                        }
                        Long OutTradeNo = Long.valueOf(outTradeNo);
                        orderMapper.updateStatus(OutTradeNo, 1);
                        log.info("订单商户订单号：" + resourcePayJson.get("out_trade_no") + "\t支付成功\t" + "用户openId：" + resourcePayJson.getJSONObject("payer").get("openid") + "\t用户支付金额：" + resourcePayJson.getJSONObject("amount").get("total"));
                    } else {
                        log.info("微信返回支付失败： 失败单号" + resourcePayJson.get("out_trade_no") + "失败状态" + resourcePayJson.get("trade_state"));
                    }
                } else {
                    log.error("微信返回支付错误摘要：" + requestBodyJson.get("summary"));
                }
            }
        } catch (Exception e) {
            result.put("code", "fail");
            result.put("message", "系统错误");
        }
        result.put("code", "SUCCESS");
        result.put("message", "成功");
        return result;
    }

    public Boolean refund(String outTradeNo, String out_refund_no, String reason, String amount) throws IOException, GeneralSecurityException, HttpCodeException, NotFoundException {
        //设置微信请求url
        HttpPost httpPost = new HttpPost(wxInformation.getWxUrl().concat(wxWayJsapi.getRefund()));
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type", "application/json;charset=utf-8");
        // 请求body参数
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode rootNode = objectMapper.createObjectNode();
        rootNode.put("out_trade_no", outTradeNo)
                .put("out_refund_no", out_refund_no)
                .put("notify_url", wxInformation.getRefundNotifyUrl())
                .put("reason", reason);
        //总金额，单位为分
        Integer amount1 = Integer.valueOf(amount);

        rootNode.putObject("amount")
                .put("refund", amount1)
                .put("total", amount1)
                .put("currency", "CNY");
        log.info("请求参数 ===> " + rootNode);
        objectMapper.writeValue(bos, rootNode);
        httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
        /**
         * 完成签名并执行请求
         * */
        CloseableHttpResponse response = wxHttpRequest.sendWX(wxHttpRequest.getVerifier()).execute(httpPost);
        int code = response.getStatusLine().getStatusCode();
        if (code == 200) {
            String bodyAsString = EntityUtils.toString(response.getEntity());
            log.info("返回的响应体是 =====》 " + bodyAsString);
            JSONObject bodyobj = JSONObject.parseObject(bodyAsString);
            String ResponseOutRefundNo = (String) bodyobj.get("out_refund_no");
            log.info("退款成功 ，退款单号：" + ResponseOutRefundNo);
            return true;
        }
        String bodyAsString = EntityUtils.toString(response.getEntity());
        log.info("返回的响应体是 =====》 " + bodyAsString);
        return false;
    }

    public Map payRefund(HttpServletRequest request) {
        Map<String, String> result = new HashMap();
        try {
            String requestBody = HttpRequestHelper.getRequestBody(request);
            log.info("退款成功响应数据是： " + requestBody);
            JSONObject requestBodyJson = JSONObject.parseObject(requestBody);
            //微信返回的证书序列号
            String serialNo = request.getHeader("Wechatpay-Serial");
            //微信返回的随机字符串
            String nonceStr = request.getHeader("Wechatpay-Nonce");
            //微信返回的时间戳
            String timestamp = request.getHeader("Wechatpay-Timestamp");
            //微信返回的签名
            String wechatSign = request.getHeader("Wechatpay-Signature");
            // 构建request，传入必要参数
            NotificationRequest request1 = new NotificationRequest.Builder().withSerialNumber(serialNo)
                    .withNonce(nonceStr)
                    .withTimestamp(timestamp)
                    .withSignature(wechatSign)
                    .withBody(requestBody)
                    .build();
            NotificationHandler handler = new NotificationHandler(wxHttpRequest.getVerifier().getVerifier(wxInformation.getMchId()), wxInformation.getV3Key().getBytes(StandardCharsets.UTF_8));
            // 验签和解析请求体
            Notification notification = handler.parse(request1);
            // 从notification中获取解密报文
            log.info("退款成功获取解密报文： " + notification.getDecryptData());
            if (notification.getDecryptData() != null) {
                if ("REFUND.SUCCESS".equals(requestBodyJson.get("event_type") + "")) {
                    JSONObject resourcePayJson = JSONObject.parseObject(notification.getDecryptData());
                    //根据微信之后返回的结果对订单进行不同的处理
                    if ("SUCCESS".equals(resourcePayJson.get("refund_status") + "")) {
                        String outTradeNo = (String) resourcePayJson.get("out_trade_no");
                        Long OutTradeNo = Long.valueOf(outTradeNo);
                        orderMapper.updateStatus(OutTradeNo, 0);
                        log.info("订单商户订单号：" + resourcePayJson.get("out_trade_no") + "\t退款成功\t" + "退款金额：" + resourcePayJson.getJSONObject("amount").get("total"));
                    } else {
                        log.info("微信返回支付失败： 失败单号" + resourcePayJson.get("out_trade_no") + "失败状态" + resourcePayJson.get("trade_state"));
                    }
                } else {
                    log.error("微信返回退款错误摘要：" + requestBodyJson.get("summary"));
                }
            }
        } catch (Exception e) {
            result.put("code", "fail");
            result.put("message", "系统错误");
            e.printStackTrace();
        }
        result.put("code", "SUCCESS");
        result.put("message", "成功");
        return result;
    }

    public String CheckAmount(ProductInfo productInfo, OrderDTO orderDTO) throws ParseException {

        //判断最低价格
        final int MIN_COUNT;
        if(productInfo.getId() <= 17) {
            MIN_COUNT = 300;
        } else {
            MIN_COUNT = 0;
        }

        //新用户价格
        Integer newUserPrice = productInfo.getNewUserPrice();
        //正常价格
        Integer productPrice = productInfo.getProductPrice();

        //获取openid
        String openid = BaseContext.getCurrentId();
        //获取前端传过来的优惠券id
        Integer couponId = orderDTO.getCouponId();
        //更改前端的金额为分
        int amount = (int) (orderDTO.getAmount() * 100);
        //不使用优惠卷
        if (!orderDTO.getIsUseDiscount()) {
            //  判断订单表中是否有订单
            if (productInfo.getProductPrice() == null && productInfo.getNewUserPrice() == null) {
                if (amount >= MIN_COUNT){
                    return amount + "";
                } else {
                    return "";
                }
            }
            //首单0.33
            if(productInfo.getId().equals(11)){
                List<Orders> ordersList = orderMapper.selectByOpenIdAll(openid);
                Invite invite= inviteMapper.selectByCode(orderDTO.getPass());
                InviteRecord inviteRecord1 = new InviteRecord();
                inviteRecord1.setOpenid(openid);
                inviteRecord1.setPass(orderDTO.getPass());
                inviteRecord1.setInviteOpenid(invite.getOpenid());
                inviteRecord1.setInviteTime(LocalDateTime.now());
                inviteMapper.updataReduceCount(invite.getOpenid());
                inviteRecordMapper.save(inviteRecord1);
                CouponBook couponBook = couponBookMapper.selectByOpenidByCouponId(invite.getOpenid(), CouponBook.ID3);
                if(ordersList.isEmpty()){
                    if(couponBook==null){
                        CouponBook couponBook1 = CouponBook.builder().couponId(CouponBook.ID3).openid(invite.getOpenid()).count(3).build();
                        couponBookMapper.save(couponBook1);
                    }else {
                        couponBookMapper.updateAddCount3(invite.getOpenid(),CouponBook.ID3);
                    }
                    return newUserPrice+"";
                }else{
                    if(couponBook==null){
                        CouponBook couponBook1 = CouponBook.builder().couponId(CouponBook.ID3).openid(invite.getOpenid()).count(1).build();
                        couponBookMapper.save(couponBook1);
                    }else {
                        couponBookMapper.updateAddCount(invite.getOpenid(),CouponBook.ID3);
                    }
                    return productPrice+"";
                }
            }
            //前端传过来的金额是正常价格
            if (amount == productPrice) {
                //if(productInfo.getId().equals(10)){
                    //LocalDate currentDate = LocalDate.now();
                    //int year = currentDate.getYear();
                    //int month = currentDate.getMonthValue();
                    //int endDay = currentDate.getDayOfMonth();
                    //int startDay = endDay-1;
                    //SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    //Date startDate = simpleDateFormat.parse(year+"-"+month+"-"+startDay+" "+"19:00:00" );
                    //Date endDate = simpleDateFormat.parse(year+"-"+month+"-"+endDay+" "+"11:00:00" );
                    //long startDateTimes = startDate.getTime();
                    //long endDateTimes = endDate.getTime();
                    //long timeMillis = System.currentTimeMillis();
                    //if(startDateTimes<timeMillis&&endDateTimes>startDateTimes){
                    //    return productPrice + "";
                    //}
                    //return "";
                //}
                return productPrice + "";
            }
            ActivityRecord activityRecord = activityRecordMapper.selectByActivityId(openid, 1);
            if (activityRecord == null) {
                return newUserPrice + "";
            }
            return "";
        } else {
            //使用优惠卷
            Coupon coupon = couponMapper.selectById(couponId);
            //判断优惠卷是否为存在
            if (coupon == null) {
                return "";
            } else {
                //优惠卷存在，判断是否拥有优惠卷大于0
                CouponBook couponBook = couponBookMapper.selectByOpenidByCouponId(openid, coupon.getCouponId());
                if (couponBook.getCount() > 0) {
                    //判断优惠卷是否过期
                    Integer value = coupon.getValue();
                    Long endAt = coupon.getEndAt();
                    long timeMillis = System.currentTimeMillis();
                    if ((endAt - timeMillis) > 0) {
                        //没有过期
                        if (productInfo.getProductPrice() == null && productInfo.getNewUserPrice() == null) {
                            if (amount >= 300) {
                                return amount + "";
                            } else {
                                return "";
                            }
                        }
                        Integer NewAmount = (productPrice - value);
                        if(NewAmount<0){
                            NewAmount=10;
                        }
                        String NewAmount1= String.valueOf(NewAmount);
                        if (NewAmount1.equals(amount + "")) {
                            return NewAmount1;
                        }
                        return "";
                    } else {
                        return "";
                    }
                }
                return "";
            }
        }

    }
}
